/**
 * Copyright (c) [2025] [何屹林]
 *
 * 保留所有权利。
 *
 * 文件名称：presolve.cpp
 * 模块功能说明：
 * 该模块定义全局变量和宏变量，定义了部分基本函数，承载了逻辑类中的预处理正则表达式的函数，并针对各种类型的正则表达式进行顺序编码。
 *
 * 华南师范大学-计算机学院-网络工程-1班
 * 作者：何屹林-20222132023
 * 完成日期：2025年7月24日
 */
#include "logic.h"

QMap<QChar,QString>C2S;
QSet<QChar>Chars;
QString resultText;

QMap<int, QString> Cd2Token{ {0, STR(END)} };
QMap<QString,int>token_makecd;

QMap<QChar,int>OpPrec{{'|',1},{'@',2},{'*',3},{'?',4}};

int capacity=0;
QVector<QString> MapStr{ "\\+", "\\|", "\\(", "\\)", "\\*", "\\?", "\\n", QString("\\") + ANY};
int NfaCnt=0;
int CdCnt=1;

QString midText="";
QString middText="";

QHash<int, int> CdPrec;
QHash<QString,int>ccdd;

QVector<int> MainCd[2];
QMap<QString,QSet<QChar>>CharSet;
QSet<QChar> CharSetSym;
QMap<QString,QChar>S2C;
//QString getText;
//QString LexCode;


//下面定义一些后续需要使用的函数，便于后面代码的编写，部分内容是在之后的开发中有需要，再回来重新写的，这类函数一律先放在presolve文件中，毕竟都是字符串层面的函数

//判断是不是字符，由于前面已经对出现在下面的字符进行了希腊字母转换，所以一定不会出现下面的字符
bool isChar(const QChar& c) {
    return !(c == '+' || c == '|' || c == '*' || c == '('
             || c == ')' || c == '?' || c == '@' || c == EXIT);
}


//映射处理正则表达式
void solve()
{
    //初始化映射表（-128~-1作为可用映射字符值避开冲突）
    for(int i=0;i<MapStr.size();++i)
    {
        C2S[char(EXIT-1-i)]=MapStr[i];
        S2C[MapStr[i]]=char(EXIT-1-i);
    }

    for(auto it=CharSet.constBegin();it!=CharSet.constEnd();++it)
    {
        CharSetSym.insert(S2C[it.key()]);
    }

    //使用map映射关系替换正则表达式中的符号
    for(auto it=S2C.constBegin();it!=S2C.constEnd();++it)
    {
        resultText.replace(it.key(),STR(it.value()));
    }

    //处理+号
    for(int i=0;i<resultText.size();i++)
    {
        //把遇到的正闭包+全部转化成*的形式，例如将a+转换为aa*
        if(resultText[i] =='+')
        {
            int k=0,j=i;
            do{
                --j;
                if(resultText[j]==')') k++;
                else if(resultText[j]=='(') k--;
            }while(k!=0);
            QString str1=resultText.mid(0,j);
            QString kstr=resultText.mid(j,i-j);
            QString str2=resultText.mid(i+1,(resultText.size()-1));
            resultText=str1+kstr+kstr+'*'+str2;
        }
    }

    for(int i=0;i<resultText.size()-1;i++)
    {
        if(
            (isChar(resultText[i])&&isChar(resultText[i+1]))
            ||(isChar(resultText[i])&&resultText[i+1]=='(')
            ||(resultText[i]==')'&&(resultText[i+1]=='('||isChar(resultText[i+1])))
            ||(resultText[i]=='*'&&(resultText[i+1]=='('||isChar(resultText[i+1])))
            ||(resultText[i]=='?'&&(resultText[i+1]=='('||isChar(resultText[i+1])))
            ||(resultText[i]=='+'&&(resultText[i+1]=='('||isChar(resultText[i+1])))
            )
        {
            QString str1=resultText.mid(0,i+1);
            QString str2=resultText.mid(i+1,(resultText.size()-1));
            resultText=str1+'@'+str2;
        }
    }

}



// 对正则表达式进行处理
void Logic::presolve() {
    // 去除空格和制表符
    getText.replace(" ","");
    getText.replace("\t","");


    // 将文本内容按行分割成一个字符串列表

    QVector<QString> lines=getText.split('\n');

    // 拼接生成NFA和DFA图的正则表达式
    for (const auto& line : lines) {
        if (line.isEmpty()) {continue;}
        int k=line.indexOf('=');
        QString l = line.mid(0, k); // 式子名称
        QString r = line.mid(k + 1);  // 式子内容
        //编码（字符串形式）
        QString codestr="";
        //编码（数字形式）
        int code;
        //单词内容
        QString letter="";
        if (l[0] == '_')  // 如果命名前有下划线，则代表该正则表达式需要生成NFA图和DFA图
        //l[1] == '_' ? (canselect(r)) : genMainCode(l, r);
        {
            //对于可选择的单纯正则表达式处理（关键字运算符等），处理或类正则表达式
            if(l[1]=='_')
            {
                if(!r.isEmpty())
                {

                    //对于可选择类，先处理好它的l和r
                    //l处理过程包括：把数字提取出来
                    QRegularExpression re("(\\d+)"); // 匹配连续的数字
                    QRegularExpressionMatch match = re.match(l);
                    if (match.hasMatch()) {
                        codestr = match.captured(1); // 获取第一个匹配的数字序列
                        code = codestr.toInt();
                        qDebug() << "提取到的数字:" << codestr << "，位数:" << codestr.length();
                    } else {
                        qDebug() << "未找到数字";
                    }

                    //r处理过程包括，根据分号分别提取内容，然后和提取的数字匹配键值对，然后把值加一
                    //生成单词编码
                    for(auto&x :r.split('|'))
                    {
                        resultText+='('+x+')'+EXIT+'|';
                        x.replace("\\","");//去除反斜杠转义符

                        int k = Cd2Token.size();
                        //CdPrec[k] = 2;
                        capacity++;
                        CdPrec.insert(capacity,2);
                        Cd2Token[k] = x;
                        ccdd.insert(x,2);
                        token_makecd.insert(x,code);
                        code++;

                    }
                }
            }
            //对于复合生成类的正则表达式处理（实数和单词等等）,分为概括类和无实义类
            else{
                //生成单词编码
                if(!r.isEmpty())
                {
                    //先处理左边提出数字codestr和code
                    QRegularExpression re("(\\d+)"); // 匹配连续的数字
                    QRegularExpressionMatch match = re.match(l);
                    if (match.hasMatch()) {
                        codestr = match.captured(1); // 获取第一个匹配的数字序列
                        code = codestr.toInt();
//                        qDebug() << "提取到的数字:" << codestr << "，位数:" << codestr.length();
                    } else {
//                        qDebug() << "未找到数字";
                    }
                    resultText+='('+r+')'+EXIT+'|';
                    bool flag =l[1]=='!';//！开头是无实义的，否则是实义的
                    int k=Cd2Token.size();
                    capacity++;

                    if(!flag)//实义类型,提取实义类型的名字
                    {
                        l=l.remove(codestr);
                        CdPrec.insert(capacity,1);
                        Cd2Token[k]=l.mid(1);
                        MainCd[0].append(k);
                        ccdd.insert(l.mid(1),1);
                        token_makecd.insert(l.mid(1),code);
                    }

                    else if(flag)
                    {
                        l=l.remove(codestr);
                        CdPrec.insert(capacity,0);
                        Cd2Token[k]=l.mid(2);
                        MainCd[1].append(k);
                        ccdd.insert(l.mid(2),0);
                        token_makecd.insert(l.mid(2),code);
                    }
                }
            }
        }


        else

        {
            if(!(r.size()<3))
            {
                MapStr.append(l);
                r=r.mid(1,r.size()-2);//从第二个符号截取到倒数第二个符号，去掉中括号
                //替换转移减号
                r.replace("\\-",STR(char(-2)));
                //替换范围运算符
                r.replace(STR(RANGE),STR(char(-1)));
                //再将转义减号转化为普通减号
                r.replace(STR(char(-2)),"-");

                int n=r.size(),i=-1;
                QVector<bool> v(n);
                //参与范围运算的字符
                while((i=r.indexOf(char(-1),i+1))!=-1)
                {
                    v[i-1]=v[i]=v[i+1]=true;
                    QChar c;
                    for(c=r.at(i-1);c<=r.at(i+1);c=QChar(c.unicode()+1))
                    {
                        CharSet[l].insert(c);
                    }
                }
                //补充剩余字符
                for(i=0;i<n;++i)
                {
                    if(!v[i])
                        CharSet[l].insert(r[i]);
                }
            }
        }
    }
    resultText.chop(1);  // 去除最后一个'|'
    //cout << "拼接后的正则表达式:\n" << outRegex << '\n';
    midText=resultText;

    //映射处理正则表达式
    solve();
    //cout << "处理后的正则表达式:\n" << outRegex << '\n';
}


